﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing; //Point
using System.Threading;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Nero_demo.Westward;
using System.Diagnostics;

namespace Nero_demo
{
    class ProcessHelper: ResourceUser
    {
        public ProcessHelper()
        {
            snapshotPath = appPath + "snapshot\\";
            mouseHelper = new MouseHelper();
            windowHelper = new WindowHelper();
            taskConfig = new TaskConfig();
        }

        public void SetTaskConfig(TaskConfig tc)
        {
            this.taskConfig = tc;
        }

        public TaskConfig GetTaskConfig()
        {
            return this.taskConfig;
        }

        public void Start()
        {
            InitWindow();
            if (taskConfig.IsWaitZeroClock)
            {
                if (WaitForZeroClock())
                {
                    ScratchCard();
                }
            }
            if (taskConfig.IsTreasureMap)
            {
                TreasureMap();
            }
            if (taskConfig.IsSecretTask)
            {
                SecretTask();
            }
            if (taskConfig.IsSearchGhostTeam)
            {
                SearchGhostTeam();
            }
            if (taskConfig.IsExpress)
            {
                ExpressTask();
                Thread.Sleep(5 * 60000);
                ReturnChangAn();
            }
            if (taskConfig.IsSearchInstanceTeam)
            {
                SearchInstanceTeam();
            }
        }

        public void TreasureMap()
        {
            InitWindow();
            TreasureMapTask();
            Thread.Sleep(15 * 60000);
            while (CheckAutoBattle(1 * 60))
            {
                Thread.Sleep(60 * 1000);
            }
            ConsumeTreasureMap();
        }

        private void QuitTeam()
        {
            // 退出队伍
            MouseClick(CoordinateWestward.TeamInfo);
            Thread.Sleep(500);
            if (!CheckImage("teamtitle.png"))
            {
                // 再次点击队伍按钮
                MouseClick(CoordinateWestward.TeamInfo);
                Thread.Sleep(500);
                // 退出队伍
                FindButtonAndClick("quitteambutton.png");
                Thread.Sleep(500);
            }
            // 关闭队伍窗口按钮
            FindButtonAndClick("closescratchbutton.png");
            Thread.Sleep(500);
        }

        /// <summary>
        /// 竞技场任务
        /// </summary>

        public void ArenaTask()
        {
            // InitWindow();
            Player.Require(this);

            // 进入长安
            MouseClick(CoordinateWestward.WorldMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.ChangAn);
            Thread.Sleep(1000);

            // 找到竞技场指引人
            MouseClick(CoordinateWestward.SceneMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.ArenaNPC);
            Player.Release();
            Thread.Sleep(10000);
            Player.Require(this);
            MouseClick(CoordinateWestward.CloseSceneMap);
            Thread.Sleep(1000);

            Point arenaNPCPos = new Point();
            ImageSearcher.FindImage(SnapshotCurrentMat(), snapshotPath + "arenanpc.png", out arenaNPCPos);

            MouseClick(arenaNPCPos);
            Thread.Sleep(5000);

            // 开始活动
            if (!FindButtonAndClick("arenabutton.png"))
            {
                LogHelper.Record("不在活动时间！");
                Player.Release();
                return;
            }

            Thread.Sleep(5000);
            if (!FindButtonAndClick("arenaicon.png"))
            {
                LogHelper.Record("未找到活动按钮！");
                Player.Release();
                return;
            }
            Thread.Sleep(5000);
            // 选择助战
            if (FindButtonAndClick("closearenapolicy.png"))
            {
                Thread.Sleep(5000);
            }


            // 循环查找匹配和自动战斗按钮
            int fightTimes = 1;
            int retryTimes = 0;

            while (fightTimes < 10 && retryTimes < 300)
            {
                int index;
                if (FindButtonsAndClick(new string[] { "matchbutton.png", "manubattle.png" }, 0.9, out index))
                {
                    if (index == 0)
                    {
                        fightTimes++;
                    }
                    retryTimes = 0;
                    Thread.Sleep(1000);
                }
                else
                {
                    retryTimes++;
                }
                Player.Release();
                Thread.Sleep(10000);
                Player.Require(this);
            }

            LogHelper.Record("竞技场完成！");
            Player.Release();

        }

        /// <summary>
        /// 运镖任务
        /// </summary>
        public void ExpressTask()
        {
            InitWindow();

            // 进入长安
            MouseClick(CoordinateWestward.WorldMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.ChangAn);
            Thread.Sleep(1000);
            // 退出队伍
            QuitTeam();
            // 和钟馗对话
            MouseClick(CoordinateWestward.SceneMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.ExpressNPC);
            Thread.Sleep(1000);
            // 点击任务
            Thread.Sleep(10000);
            FindButtonAndClick("expressbutton.png");
            Thread.Sleep(1000);
            // 点击确认
            FindButtonAndClick("confirmbutton.png");

            int expressTimes = 1;
            int retryTimes = 0;

            while (expressTimes < 3 && retryTimes < 40)
            {
                if (FindButtonAndClick("expressbutton.png"))
                {
                    expressTimes++;
                    retryTimes = 0;
                    Thread.Sleep(1000);
                    // 点击确认
                    FindButtonAndClick("confirmbutton.png");
                }
                else
                {
                    if (!CheckImage("autobattle.png"))
                    {
                        retryTimes++;
                    }
                }

                Thread.Sleep(10000);
            }
        }

        public void ReturnChangAn()
        {
            InitWindow();
            // 返回长安
            string[] closeButtons = { "cancelbutton.png", "closebonusbutton.png", "closescratchbutton.png", "close100.png" };

            bool found = false;
            int foundTimes = 0;

            do
            {
                found = false;
                foreach (var closeButton in closeButtons)
                {
                    if (FindButtonAndClick(closeButton))
                    {
                        Thread.Sleep(500);
                        found = true;
                        foundTimes++;

                        break;
                    }
                }
            }
            while (found && foundTimes <= 10 * closeButtons.Length); // 使用物品的关闭按钮可能比较多
            if (found)
            {
                LogHelper.Record("存在无法关闭的弹窗，返回长安失败");
                windowHelper.ScreenShot("Debug-CannotClose-Changan" + ".png");
                return;
            }

            for (int i = 0; i < 2; i++)
            {
                // 进入长安
                MouseClick(CoordinateWestward.WorldMap);
                Thread.Sleep(1000);
                MouseClick(CoordinateWestward.ChangAn);
                Thread.Sleep(1000);
                // 检查是否在长安
                if (CheckImage("changanlogo.png"))
                {
                    FindButtonAndClick("expandmenu.png");
                    Thread.Sleep(100);
                    LogHelper.Record("已返回长安");
                    break;
                }
                else
                {
                    windowHelper.ScreenShot("Debug-NotReturn-Changan" + ".png");
                    LogHelper.Record("返回长安失败");
                }
            }
        }

        public void SnapshotCurrent()
        {
            InitWindow();
            windowHelper.ScreenShot(currentShotFile);
            // logEvent("文件保存在:" + currentShotFile);
        }

        private OpenCvSharp.Mat SnapshotCurrentMat()
        {
            InitWindow();
            return windowHelper.ScreenShot();
        }

        private void PrintMousePoint()
        {
            Point point = new Point();

            MouseHelper.GetCursorPos(ref point);

            LogHelper.Record(string.Format("mouse {0} {1}", point.X, point.Y));
        }

        private void OpenPackage()
        {
            MouseClick(CoordinateWestward.Package);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.ArrangePackage);
        }

        private bool WaitForZeroClock()
        {
            // 获取当前时间
            DateTime now = DateTime.Now;

            if (now.Hour == 0)
            {
                return false;
            }

            // 计算到下一个午夜的时间间隔
            TimeSpan timeUntilMidnight = new TimeSpan(24, 2, 0) - now.TimeOfDay;

            LogHelper.Record("午夜后启动任务");

            // 等待直到午夜
            Thread.Sleep(timeUntilMidnight);

            // 在午夜执行的操作
            LogHelper.Record("It's 00:02 now!");

            return true;
        }

        // 藏宝图任务
        private void TreasureMapTask()
        {
            // 返回长安
            ReturnChangAn();
            // 进入长安
            MouseClick(CoordinateWestward.WorldMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.ChangAn);
            Thread.Sleep(1000);
            // 和店小二对话
            MouseClick(CoordinateWestward.SceneMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.TreasureMapNPC);
            Thread.Sleep(1000);
            // 点击任务
            Thread.Sleep(10000);
            if (!FindButtonAndClick("treasurebutton.png"))
            {
                LogHelper.Record("未找到藏宝图任务按钮");
                return;
            }
            // 启动任务
            Thread.Sleep(2000);
            MouseClick(CoordinateWestward.ChangAn);
            Thread.Sleep(1000);
            // MouseClick(CoordinateWestward.FirstTaskMenu);
            if (!FindButtonAndClick("maptask.png"))
            {
                LogHelper.Record("未找到宝图任务");
                return;
            }
        }

        // 使用藏宝图
        private void ConsumeTreasureMap()
        {
            OpenPackage();
            Thread.Sleep(1000);

            // 双击使用藏宝图
            Point point = new Point();
            if (!ImageSearcher.FindImage(SnapshotCurrentMat(), snapshotPath + "treasuremap.png", out point))
            {
                LogHelper.Record("包裹中未找到藏宝图");
                return;
            }
            LogHelper.Record("藏宝图: " + point.X.ToString() + ", " + point.Y.ToString());
            MouseDoubleClick(point);

            int maxRetryTimes = 20;
            int retryTimes = 0;
            int mapCount = 0;

            // 循环查找使用按钮
            while (retryTimes < maxRetryTimes)
            {
                Thread.Sleep(5000);
                point = new Point();
                if (!ImageSearcher.FindImage(SnapshotCurrentMat(), snapshotPath + "treasureuse.png", out point))
                {
                    // logEvent("未找到藏宝图按钮");
                    retryTimes++;
                    continue;
                }
                mapCount++;
                LogHelper.Record(string.Format("藏宝图按钮{0}: {1}, {2}", mapCount, point.X, point.Y));
                // 检测查找到的位置
                if (point.X > 900)
                {
                    LogHelper.Record("藏宝图按钮位置异常");
                    retryTimes++;
                    continue;
                }
                MouseClick(point);
                retryTimes = 0;
            }
            LogHelper.Record("宝图已经挖完");
            ReturnChangAn();
        }

        // 梦幻刮刮乐
        public void ScratchCard()
        {
            InitWindow();
            int retryTimes = 0;

            // 打开刮刮乐按钮
            while (retryTimes < 2)
            {
                if (FindButtonAndClick("openscratchbutton.png"))
                {
                    break;
                }
                else
                {
                    retryTimes++;
                    Thread.Sleep(60 * 1000);
                }
            }

            if (retryTimes == 3)
            {
                return;
            }

            DoScratch(CoordinateWestward.ScratchCardTopLeft, CoordinateWestward.ScratchCardBottomRight);
            Thread.Sleep(500);
            FindButtonAndClick("closescratchbutton.png");
            Thread.Sleep(500);
            FindButtonAndClick("closebonusbutton.png");
            Thread.Sleep(500);
        }

        private bool DoScratch(Point topLeft, Point bottomRight)
        {
            int steps = 5;
            for (int y = topLeft.Y; y < bottomRight.Y; y += steps)
            {
                MouseDragX(topLeft.X, bottomRight.X, y);
                Thread.Sleep(100);
            }
            return true;
        }

        // 秘境降妖任务
        public void SecretTask()
        {
            InitWindow();
            // 进入东海湾
            MouseClick(CoordinateWestward.WorldMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.EastSeaBay);
            Thread.Sleep(3000);
            // 和云乐游对话
            MouseClick(CoordinateWestward.SceneMap);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.SecretNPC);
            Thread.Sleep(1000);
            // 点击任务
            Thread.Sleep(8000);
            if (!FindButtonAndClick("secretbutton.png"))
            {
                LogHelper.Record("未找到秘境降妖任务按钮");
                windowHelper.ScreenShot("Debug-CannotFind-Secretbutton" + ".png");
                return;
            }
            Thread.Sleep(500);
            // 是否周一选择秘境
            if (CheckImage("selectsecretflag.png"))
            {
                MouseClick(CoordinateWestward.SecretSeaButton);
                Thread.Sleep(500);
                FindButtonAndClick("confirmbutton.png");
            }
            // 启动任务
            Thread.Sleep(2000);
            MouseClick(CoordinateWestward.SecretLevel1);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.SecretConfirm);
            Thread.Sleep(5000);
            MouseClick(CoordinateWestward.SecretLevel1Task);

            // 12分钟后开始循环查找进入战斗按钮
            // Thread.Sleep(12 * 60 * 1000);
            int retryTimes = 0;

            while (retryTimes < 30)
            {
                if (FindButtonAndClick("fightbutton.png"))
                {
                    retryTimes = 0;
                    Thread.Sleep(1000);
                    continue;
                }
                else
                {
                    if (!CheckImage("autobattle.png"))
                    {
                        retryTimes++;
                    }
                    else
                    {
                        retryTimes = 0;
                    }
                }

                Thread.Sleep(10000);
            }

            // 五分钟后开始循环查找进入战斗按钮
            /*
            Thread.Sleep(5 * 60 * 1000);
            int fightTimes = 1;
            retryTimes = 0;


            while (fightTimes < 3 && retryTimes < 30)
            {
                if (FindButtonAndClick("fightbutton.png"))
                {
                    fightTimes++;
                    retryTimes = 0;
                    Thread.Sleep(1000);
                }
                else
                {
                    retryTimes++;
                }

                Thread.Sleep(10000);
            }
            */

            // 五分钟后退出秘境降妖
            Thread.Sleep(5 * 60 * 1000);
            MouseClick(CoordinateWestward.ChangAn);
            Thread.Sleep(1000);
            MouseClick(CoordinateWestward.SecretExit);
            Thread.Sleep(1000);
            LogHelper.Record("退出秘境降妖");
            Thread.Sleep(1000);
            ReturnChangAn();
        }

        /// <summary>
        /// 点赞任务
        /// </summary>
        public void LikeTask()
        {
            const int delayTime = 100;
            InitWindow();

            // 聊天按钮
            if (!FindButtonAndClick("chatbutton.png"))
            {
                return;
            }
            Thread.Sleep(delayTime * 5);

            // 空间按钮
            if (!FindButtonAndClick("spacebutton.png"))
            {
                return;
            }
            Thread.Sleep(delayTime);

            // 点赞
            for (int i = 0; i < 10; i++)
            {
                FindButtonAndClick("heartbutton.png");
                Thread.Sleep(delayTime);
                for (int j = 0; j < 30; j++)
                {
                    MouseWheel(-100000);
                }
                Thread.Sleep(delayTime * 10);
            }

            FindButtonAndClick("foldchatbutton.png");
            Thread.Sleep(delayTime);
        }

        // 混捉鬼队
        public void SearchGhostTeam()
        {
            const int timeout_s = 120 * 60;
            Stopwatch stopwatch = new Stopwatch();

            do
            {
                stopwatch.Start();
                SearchTeam("ghosttask.png", "混入捉鬼队!");
                Thread.Sleep(10 * 60 * 1000);

                while (CheckAutoBattle())
                {
                    Thread.Sleep(60 * 1000);
                }
                LogHelper.Record("长时间未进入战斗, 退出队伍");
                FindButtonAndClick("quitteambutton.png");
                ReturnChangAn();
                stopwatch.Stop();
            } while (stopwatch.ElapsedMilliseconds < timeout_s * 1000);

            // 退出队伍
            LogHelper.Record("捉鬼时间到, 退出队伍");
            FindButtonAndClick("quitteambutton.png");
            ReturnChangAn();
        }

        // 混副本队
        public void SearchInstanceTeam()
        {
            const int timeout_s = 90 * 60;
            Stopwatch stopwatch = new Stopwatch();

            do
            {
                stopwatch.Start();
                SearchTeam("instancetask.png", "混入副本队!");
                Thread.Sleep(10 * 60 * 1000);

                while (CheckAutoBattle())
                {
                    Thread.Sleep(60 * 1000);
                }
                LogHelper.Record("长时间未进入战斗, 退出队伍");
                FindButtonAndClick("quitteambutton.png");
                ReturnChangAn();
                stopwatch.Stop();
            } while (stopwatch.ElapsedMilliseconds < timeout_s * 1000);

            // 退出队伍
            LogHelper.Record("副本时间到, 退出队伍");
            FindButtonAndClick("quitteambutton.png");
            ReturnChangAn();
        }

        // 混队
        private void SearchTeam(string img, string tips)
        {
            const int delayTime = 500;
            const int retryTimes = 60;
            InitWindow();
            // 点击队伍信息按钮
            MouseClick(CoordinateWestward.TeamInfo);
            Thread.Sleep(delayTime * 3);
            // 便捷组队
            if (!FindButtonAndClick("searchteambutton.png"))
            {
                // 重试一次
                MouseClick(CoordinateWestward.TeamInfo);
                Thread.Sleep(delayTime * 3);
                if (CheckImage("teamtitle.png"))
                {
                    FindButtonAndClick("quitteambutton.png");
                    Thread.Sleep(delayTime);
                }
                if (!FindButtonAndClick("searchteambutton.png"))
                {
                    windowHelper.ScreenShot("Debug-SearchTeam-Fail" + ".png");
                    LogHelper.Record(tips + "失败！");
                    return;
                }
            }
            Thread.Sleep(delayTime);
            if (CheckImage("alltasks.png"))
            {
                // 日常任务
                if (!FindButtonAndClick("dailytask.png"))
                {
                    return;
                }
            }
            Thread.Sleep(delayTime);
            // 捉鬼任务
            if (!FindButtonAndClick(img))
            {
                return;
            }
            Thread.Sleep(delayTime * 3);
            // 自动匹配
            if (!FindButtonAndClick("automatch.png"))
            {
                return;
            }
            Thread.Sleep(delayTime);
            // 记录何时进入队伍
            int retryTime = 0;
            while (!CheckImage("quitteambutton.png") && retryTime < retryTimes)
            {
                Thread.Sleep(30 * 1000);
                retryTime++;
            }
            if (retryTime < retryTimes)
            {
                LogHelper.Record(tips);
            }
            else
            {
                LogHelper.Record(tips + "超时！");
            }

        }

        // 检查是否在自动战斗的场景中
        private bool CheckAutoBattle(int timeout_s = 5 * 60)
        {
            bool ret = false;

            const int period = 5;
            int times = timeout_s / period;

            int checkTimes = 0;

            while (checkTimes < times)
            {
                if (CheckImage("autobattle.png"))
                {
                    ret = true;
                    break;
                }
                Thread.Sleep(period * 1000);
                checkTimes++;
            }

            return ret;
        }

        private void MouseClick(Point point)
        {
            mouseHelper.MouseClick(new Point(windowHelper.leftBase + point.X, windowHelper.topBase + point.Y));
        }

        private void MouseWheel(int delta)
        {
            mouseHelper.MouseWheel(delta);
        }

        private void MouseDragX(int startx, int endx, int y)
        {
            mouseHelper.MouseDragX(windowHelper.leftBase + startx, windowHelper.leftBase + endx, windowHelper.topBase + y);
        }

        private void MouseDoubleClick(Point point)
        {
            mouseHelper.MouseDoubleClick(new Point(windowHelper.leftBase + point.X, windowHelper.topBase + point.Y));
        }

        private bool FindButtonAndClick(string name)
        {
            Point buttonPos = new Point();
            if (!ImageSearcher.FindImage(SnapshotCurrentMat(), snapshotPath + name, out buttonPos))
            {
                LogHelper.Record("未找到 " + name);
                return false;
            }

            MouseClick(buttonPos);
            LogHelper.Record("点击 " + name);
            return true;
        }

        private bool FindButtonsAndClick(string[] names, double threshold, out int index)
        {
            index = -1;
            foreach (var name in names)
            {
                index++;
                Point buttonPos = new Point();
                if (ImageSearcher.FindImage(SnapshotCurrentMat(), snapshotPath + name, out buttonPos, threshold))
                {
                    MouseClick(buttonPos);
                    LogHelper.Record("点击 " + name);
                    return true;
                }
            }

            return false;
        }

        private bool CheckImage(string name)
        {
            Point buttonPos = new Point();
            return ImageSearcher.FindImage(SnapshotCurrentMat(), snapshotPath + name, out buttonPos);
        }

        public override void ResourceGot()
        {
            InitWindow();
        }

        public bool InitWindow()
        {
            return windowHelper.InitWindow(Name);
        }

        public void ChangeName(string newName)
        {
            Name = newName;
            windowHelper.SetWindowName(Name);
        }

        public Resource Player { private get; set; }

        private MouseHelper mouseHelper;
        private WindowHelper windowHelper;
        private TaskConfig taskConfig;

        private string appPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
        private string snapshotPath;
        private static string currentShotFile = "当前.png";
    }
}
